/*
    Quaxx - Just another ataxx clone
    Copyright (C) 2010  Manuel Córdoba Ruiz

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
/**
@file tablero.h
@author Manuel Cordoba
**/

#include <QWidget>
#include <QPainter>
#include <QMouseEvent>
#include <QImage>
#include <QFile>
#include <QTimer>
//#include <QString>

#define CASILLA_VACIA 0
#define CASILLA_J1 1
#define CASILLA_J2 2
#define TAM_FICHA 80

using namespace std;

struct casilla{
	int fila, columna;
};

struct estado{
	int tab[50];
};

class Tablero : public QWidget {
	Q_OBJECT
	private:
		int tab[7][7];  // Matriz de enteros que representa el tablero. Función de abstracción: entero 0 casilla vacía, entero 1 jugador 1, entero 2 jugador 2
		int turno;  // Entero que indica el turno del jugador
		int col_origen, fila_origen;
		int pos_x, pos_y;
		bool casilla_sel;
		int index_movimientos;
		QList<estado> movimientos;  // Lista que almacena los distintos estados del tablero para poder deshacer y rehacer movimientos.
		int fichas[2];  // Vector de dos enteros que indica el numero de fichas que tiene cada jugador en el tablero.
		int tipo_oponente;  // Tipo de jugador: 0 Humano, 1 Ordenador
		int ficha1, ficha2;  // Variables auxiliares para almacenar informacion (de forma numerica) de los colores de las fichas.
		QImage fondo, imagenficha1, imagenficha2;  // Atributos para guardar las imagenes del fondo y las fichas de los 2 jugadores
		QString coloresfichas[6];
		int retrocesos;

		// Funciones

		casilla getCasilla(int x, int y);

		/**
		@brief sobrecarca del evento mousePress
		**/
		void mousePressEvent(QMouseEvent *event);


		/**
		@brief sobrecarca del evento mouseMoveEvent
		**/
		void mouseMoveEvent(QMouseEvent *event);

		/**
		@brief sobrecarca del evento mouseRelease
		**/
		void mouseReleaseEvent(QMouseEvent *event);

		/**
		@brief Calcula el numero de fichas adyacentes que hay alrededor de una ficha dada para saber cuantas fichas se comeria.
		@param fila entero que indica la fila de la casilla que queremos calcular
		@param columna entero que indica la columna de la casilla
		@return numero de fichas adyacentes (fichas que cambiarian de color y pasarian a ser del jugador que movio)
		**/
		int cuantasCome(int fila, int columna);

		/**
		@brief Metodo que comprueba una jugada
		@param fila
		@param columna
		**/
		void compruebaMovimiento(int fila, int columna);
		
		/**
		@brief Metodo que comprueba si se dan alguna de las condiciones para final de partida
		**/
		void compruebaGanar();

		/**
		@brief Cambia el turno
		**/
		void cambiaturno();

		/**
		@brief Comprueba si un jugador puede o no mover
		@param jugador entero que indica el jugador que se quiere comprobar (1 o 2)
		@return true si puede mover o false si no puede
		**/
		bool puedeMover(int jugador);

		/**
		@brief Guarda una copia del estado actual del tablero y el turno en una lista
		**/
		void guardaMovimiento();

	protected:

		/**
		@brief Evento paint, renderiza el aspecto visual del tablero.
		@param event evento
		**/
		void paintEvent(QPaintEvent *event);

	public:

		/**
		@brief Constructor. Inicializa un tablero.
		**/
		Tablero();

		/**
		@brief Destructor. No hace nada.
		**/
		~Tablero();

		/**
		@brief Devuelve que hay en una casilla:
		@return  0 libre, 1 ficha del jugador 1, 2 ficha del jugador 2
		**/
		int get(int fila, int col);

		/**
		@brief Devuelve el jugador al que le toca mover.
		@return entero que indica el jugador 1 o 2
		**/
		int getTurno();
		int getColorFicha(int jugador);

		/**
		@brief Devuelve el tipo de oponente
		@return entero que indica el tipo de oponente: 0 humano, 1 ordenador.
		**/
		int getTipoOponente();

	public slots:

		/**
		@brief Reinicia el tablero. Crea una nueva partida.
		**/
		void nuevo();

		/**
		@brief Guarda la partida actual en el archivo dado por filename
		@param fileName QString que indica el nombre del archivo.
		@return true si todo fue bien o false si hubo algun error
		**/
		bool guardar(const QString &fileName);

		/**
		@brief Abre la partida guardada en el archivo dado por filename
		@param fileName QString que indica el nombre del archivo.
		@return true si todo fue bien o false si hubo algun error
		**/
		bool abrir(const QString &fileName);

		/**
		@brief Establece el color de la ficha
		@param jugador entero que indica el jugador (1 o 2)
		@param color entero que indica el color de la ficha
		**/
		void setColorFicha(int jugador, int color);

		/**
		@brief Establece el tipo de oponente: humano u ordenador
		@param tipo entero que indica el jugador: 0 humano, 1 ordenador
		**/
		void setTipoOponente(int tipo);

		/**
		@brief Vuelve al estado anterior que haya sido guardado. Deshace un movimiento
		**/
		void anterior();

		/**
		@brief Vuelve al estado siguiente si lo hay.
		**/
		void siguiente();

		/**
		@brief Interfaz para generaMovimiento que espera 1.5 segundos para llamarlo
		**/
		void mover();

	private slots:
		/**
		@brief Genera un movimiento sobre el tablero para el jugador 2
		**/
		void generaMovimiento();

	signals:
		/**
		@brief Señal de turno cambiado.
		@param QString con el mensaje a mostrar en la barra de estado.
		**/
		void turnocambiado(QString);

		/**
		@brief Señal de que el jugador ha ganado
		@param int entero que indica el jugador
		**/
		void ganador(QString);

};

